#include "libORCL/ORCL.h"
#include "libORCL/ORCL_size.h"
#include <getopt.h>

int main(int argc,char** argv){

    // 服务器编号
    int server_num = -1;

    static struct option opts[] = {
        {"server_num", required_argument, 0, 'n'},
    };

    while (1){
        int c = getopt_long(argc, argv, "n:", opts, NULL);

        if (c == -1)
        {
            break;
        }

        switch (c){
            case 'n':
                server_num = atoi(optarg);
                break;
            
            default:
                printf("Invalid argument %d\n", c);
                assert(false);
        }
    }

    assert(server_num>=0);

    // 解析参数，我们现在只加入一个参数就是节点编号，两个进程分布在两个节点上
    // 在两个网卡之间负载均衡
    int port_index = server_num % 2;
    // 绑定的CPU和网卡是反着的
    int numa_id = (server_num + 1) % 2;

    // 下面进行连接
    // 测试一下初始化
    struct orcl_context* orcl_ctx = orcl_context_init(server_num,0,2,1,2,0,port_index,numa_id,NULL,M_2,16*server_num+1,NULL,0);

    // 初始化一下缓冲区
    memset((void *)orcl_ctx->message_buffer, 0, orcl_ctx->message_buffer_size);

    char* buf = (char *)orcl_ctx->message_buffer;

    // 0号节点执行发送
    if(server_num == 0){
        buf[0] = 'a';        
        orcl_inner_group_rdma_write(orcl_ctx, numa_id, 0, 0, 64);
    }

    if (server_num == 1)
    {
        sleep(1);
        if(buf[0] == 'a'){
            printf("单次传输正确\n");
        }
    }

    // 迭代传输，随机位置传输很多
    if(server_num == 0){
        uint64_t seed = 0xdeadbeef;
        // 这是随机数
        for (int i = 0; i < server_num * 1000000; i++)
        {
            // 一个血妈神奇的随机数生成机制，最后生成的随机数要放在seed中
            orcl_fastrand(&seed);
        }

        int i;
        for(i = 0; i < 65536; i++){
            int _size = (int)(orcl_fastrand(&seed) % 1024 + 1);
            int _offset = (int)((orcl_fastrand(&seed) % (orcl_ctx->message_buffer_size - _size)) / 64) * 64;

            // 指向发送
            orcl_inner_group_rdma_write(orcl_ctx, 1, _offset, _offset, _size);
        }

        printf("传输完成\n");
    }else{
        sleep(3);
    }

    // 下面引入batch，建立多个上下文，分别发送
    struct orcl_context* ctx_arr[4];

    ctx_arr[0] = orcl_ctx;

    int i;
    for(i = 1; i < 4; i++){
        // 取消大页之后没有
        ctx_arr[i] = orcl_context_init(server_num,0,2,1,2,0,
            port_index,numa_id,NULL,M_2,16*server_num+1,orcl_ctx,i);
    }

    // 检测其他的上下文能不能进行传输工作
    // 单次传输，分别使用不同的上下文，写0、64、128、192，这几个位置
    if(server_num == 0){
        for(i = 0; i < 4; i++){
            buf[i*64] = 'b';
            // 发送出去
            orcl_inner_group_rdma_write(ctx_arr[i], 1, i*64, i*64, 1);
        }
    }else{
        // 等待接收
        sleep(1);
        for(i = 0; i < 4; i++){
            if(buf[i*64] == 'b'){
                printf("单次传输成功\n");
            }else{
                printf("出现错误\n");
            }
        }
    }
    


    

    return 1;
}